#ifndef NETCLIENT_H
#define NETCLIENT_H

#include <QObject>
#include <QNetworkAccessManager>
#include <QWebSocket>
#include <QProtobufSerializer>
#include <QNetworkReply>

#include "../model/data.h"
#include "../debug.h"

namespace model
{
    class DataCenter;
}
namespace network
{
    class NetClient : public QObject
    {
        Q_OBJECT
    public:
        NetClient(model::DataCenter *dataCenter);

        // 验证网络连通
        void ping();
        // 初始化webSocket服务器
        void initWebSocket();
        // 发送身份认证请求
        void sendAuth();

        // 处理webSocket通知
        void handleWsResponse(const LYZ::NotifyMessage &notifyMessage);
        // 处理新消息通知
        void handleWsMessage(const model::MessageInfo &message);

        // 封装发送http请求的逻辑
        QNetworkReply *sendHttpReq(const QString &apiPath, const QByteArray &body);

        // 封装处理http响应的逻辑
        template <class T>
        std::shared_ptr<T> handleHttpRsp(QNetworkReply *httpRsp, bool &ok, QString &reason)
        {
            // 先判断http请求是否出错
            if (httpRsp->error() != QNetworkReply::NoError)
            {
                ok = false;
                reason = "HTTP 请求出错: " + httpRsp->errorString();
                httpRsp->deleteLater();
                return nullptr;
            }

            // 提取响应信息
            QByteArray body = httpRsp->readAll();

            // 进行反序列化
            std::shared_ptr<T> rsp = std::make_shared<T>();
            rsp->deserialize(&_serializer, body);

            if (!rsp->success())
            {
                ok = false;
                reason = "服务处理失败: " + rsp->errmsg();
                httpRsp->deleteLater();
                return nullptr;
            }

            httpRsp->deleteLater();
            return rsp;
        }

        void getMyself(const QString &loginSessionId);
        void getFriendList(const QString &loginSessionId);
        void getChatSessionList(const QString &loginSessionId);
        void getApplyList(const QString &loginSessionId);
        void getRecentMsg(const QString &loginSessionId, const QString &chatSessionId, bool );
        void sentMessage(const QString &loginSessionId, const QString &chatSessionId,
                         model::MessageType messageType, const QByteArray &content, const QString &extraInfo = "");

        void receiveMessage(const QString &chatSessionId, const model::MessageInfo &message);
        void changeNickname(const QString &loginSessionId, const QString &newName);
    private:
        QString makeRequestId();


    private:
#if TEST_CONNECTION
        const QString HTTP_URL = "http://127.0.0.1:8000";
        const QString WEBSOCKET_URL = "ws://127.0.0.1:8001";
#else
        const QString HTTP_URL = "http://101.126.65.233:8087";
        const QString WEBSOCKET_URL = "ws://101.126.65.233:8086";
#endif

    private:
        model::DataCenter *_dataCenter;

        QNetworkAccessManager _httpClient;
        QWebSocket _webSocketClient;

        // 序列化器
        QProtobufSerializer _serializer;
    signals:
    };
}

#endif // NETCLIENT_H
